package com.ds.rad.service;

import com.alibaba.fastjson.JSONObject;
import com.ds.annotation.MethodChinaName;
import com.ds.common.JDSException;
import com.ds.common.md5.MD5InputStream;
import com.ds.common.util.StringUtility;
import com.ds.config.ErrorListResultModel;
import com.ds.config.ErrorResultModel;
import com.ds.config.ListResultModel;
import com.ds.config.ResultModel;
import com.ds.context.JDSActionContext;
import com.ds.esd.annotation.ui.Dock;
import com.ds.esd.annotation.ui.EUFileType;
import com.ds.esd.bean.view.CustomModuleBean;
import com.ds.esd.engine.ESDClient;
import com.ds.esd.engine.ESDFacrory;
import com.ds.esd.engine.EUModule;
import com.ds.esd.engine.ProjectVersion;
import com.ds.esd.engine.enums.PackagePathType;
import com.ds.esd.engine.enums.PackageType;
import com.ds.esd.tool.component.BlockComponent;
import com.ds.esd.tool.component.ModuleComponent;
import com.ds.esd.util.XUIUtil;
import com.ds.rad.bean.XUIFile;
import com.ds.rad.bean.XUIFileVersion;
import com.ds.rad.bean.XUIModule;
import com.ds.rad.bean.XUIParas;
import com.ds.vfs.FileInfo;
import com.ds.vfs.FileVersion;
import com.ds.vfs.Folder;
import com.ds.vfs.VFSConstants;
import com.ds.vfs.ct.CtVfsFactory;
import com.ds.vfs.ct.CtVfsService;
import com.ds.web.util.PageUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Controller
@RequestMapping(value = {"/RAD/"})
@MethodChinaName(cname = "XUI编辑器")
public class VFSService {
    @MethodChinaName(cname = "添加文件夹")
    @RequestMapping(value = {"addFolder"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> addFolder(String path, String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            Folder folder = version.createFolder(path);
            result.setData(new XUIFile(folder, version));
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }

    @MethodChinaName(cname = "刷新工程")
    @RequestMapping(value = {"reLoadProject"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> reLoadProject(String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();
        try {
            getClient().reLoadProject(projectName);
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }


    @MethodChinaName(cname = "添加普通文件")
    @RequestMapping(value = {"addTextFile"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> addTextFile(String path, String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();

        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            FileInfo fileInfo = getClient().saveFile(new StringBuffer("{}"), path, projectName);
            result.setData(new XUIFile(fileInfo, version));
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }

    @MethodChinaName(cname = "添加页面")
    @RequestMapping(value = {"addClass"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> addClass(String className, String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);

            if (className.indexOf(".") > -1) {
                String packageName = className.substring(0, className.lastIndexOf("."));
                String simClassName = className.substring(className.lastIndexOf(".") + 1);
                simClassName = XUIUtil.formatJavaName(simClassName, true);
                className = packageName + "." + simClassName;
            }

            EUModule module = getClient().getModule(className, version.getVersionName(), true);
            if (module == null) {
                module = version.createModule(className);
                BlockComponent blockComponent = new BlockComponent(Dock.fill, module.getName() + ModuleComponent.DefaultTopBoxfix);
                module.getComponent().addChildren(blockComponent);
                module.getComponent().setCurrComponent(blockComponent);
                getClient().saveModule(module, false);
                //   result.setData(new XUIFile(module));
            } else {
                throw new JDSException("页面已存在！");
            }
            result.setData(new XUIFile(module));
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }

    @MethodChinaName(cname = "添加文件")
    @RequestMapping(value = {"uploadFiles"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> uploadFiles(String uploadpath, String projectName, @RequestParam("files") MultipartFile files, @RequestParam("file") MultipartFile file) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();
        if (uploadpath == null) {
            uploadpath = "";
        }

        if (files == null) {
            files = file;
        }
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            if (uploadpath.equals(projectName)) {
                uploadpath = "";
            }
            Folder tfolder = getClient().getFolderByPath(uploadpath, version.getVersionName());
            if (tfolder == null) {
                tfolder = version.createFolder(uploadpath);
            }
            try {
                FileInfo fileInfo = getClient().uploadFile(new MD5InputStream(files.getInputStream()), tfolder.getPath() + files.getOriginalFilename(), projectName);
                result.setData(new XUIFile(fileInfo, version));
            } catch (IOException e) {
                throw new JDSException(e);
            }
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }


    @MethodChinaName(cname = "导入文件")
    @RequestMapping(value = {"importFile"}, method = {RequestMethod.GET, RequestMethod.POST})
    public @ResponseBody
    ResultModel<List<XUIFile>> importFile(String id, String tpath, String projectName) {
        ResultModel<List<XUIFile>> result = new ResultModel<List<XUIFile>>();
        List<XUIFile> xuiFiles = new ArrayList<XUIFile>();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            String[] filePaths = StringUtility.split(id, ";");
            List<Object> objects = getClient().importFile(Arrays.asList(filePaths), tpath, projectName);
            for (Object obj : objects) {
                if (obj instanceof EUModule) {
                    xuiFiles.add(new XUIFile((EUModule) obj));
                } else if (obj instanceof FileInfo) {
                    xuiFiles.add(new XUIFile((FileInfo) obj, version));
                }
            }
            result.setData(xuiFiles);
        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }


    @MethodChinaName(cname = "拷贝文件夹")
    @RequestMapping(value = {"copy"}, method = {RequestMethod.GET, RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> copy(String spath, String tpath, String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            Object obj = getClient().copy(projectName, spath, tpath);
            if (obj instanceof EUModule) {
                result.setData(new XUIFile((EUModule) obj));
            } else if (obj instanceof FileInfo) {
                result.setData(new XUIFile((FileInfo) obj, version));
            } else if (obj instanceof Folder) {
                result.setData(new XUIFile((Folder) obj, version));
            }

        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }


    @MethodChinaName(cname = "获取文件内容")
    @RequestMapping(value = {"getFileContent"}, method = {RequestMethod.GET})
    public @ResponseBody
    ResultModel<XUIModule> getFileContent(String path, String className, String projectName) {
        ResultModel<XUIModule> result = new ResultModel<XUIModule>();
        XUIModule xuiModule = new XUIModule();
        String json = "{}";
        try {

            if (path != null && path.indexOf(VFSConstants.URLVERSION) > -1) {
                FileVersion version = CtVfsFactory.getCtVfsService().getFileVersionByPath(path);
                json = getClient().readFileAsString(path, projectName);
                ModuleComponent moduleComponent = JSONObject.parseObject(json, ModuleComponent.class);
                JDSActionContext.getActionContext().getContext().put("className", className + "V" + version.getIndex());
                moduleComponent.setClassName(className + "V" + version.getIndex());
                json = getClient().genJSON(moduleComponent, null, true).toString();

            } else if (className != null && !className.equals("")) {
                if (className.endsWith(".cls")) {
                    className = className.substring(0, className.length() - ".cls".length());
                    JDSActionContext.getActionContext().getContext().put("className", className);
                }
                EUModule module = getClient().getModule(path, projectName, true);
                if (module == null) {
                    module = getClient().createModule(className, projectName);
                    getClient().saveModule(module, false);
                }
                json = getClient().genJSON(module, null, true).toString();
            } else if (path.endsWith(".cls")) {
                EUModule module = getClient().getModule(path, projectName, true);
                if (module == null) {
                    EUModule euModule = getClient().createModule(className, projectName);
                    getClient().saveModule(euModule, false);
                }
                json = getClient().genJSON(module, null, true).toString();

            } else {
                json = getClient().readFileAsString(path, projectName);
            }
            xuiModule.setContent(json);
            result.setData(xuiModule);
        } catch (Exception e) {
            e.printStackTrace();
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }
        return result;
    }

    @MethodChinaName(cname = "删除文件")
    @RequestMapping(value = {"delFile"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIModule> delFile(String paths, String projectName) {
        ResultModel<XUIModule> result = new ResultModel<XUIModule>();
        XUIModule xuiModule = new XUIModule();
        List<XUIFile> modules = xuiModule.getFiles();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            if (paths != null && paths.equals(projectName)) {
                getClient().delProject(getClient().getProjectByName(projectName).getId());
            } else {
                String[] filePath = StringUtility.split(paths, ";");
                version.delFile(Arrays.asList(filePath));
            }

        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }

    @MethodChinaName(cname = "重新命名文件")
    @RequestMapping(value = {"reName"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIFile> reName(String path, String newName, String projectName) {
        ResultModel<XUIFile> result = new ResultModel<XUIFile>();

        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            Object obj = getClient().reName(projectName, path, newName);
            if (obj instanceof EUModule) {
                result.setData(new XUIFile((EUModule) obj));
            } else if (obj instanceof FileInfo) {
                result.setData(new XUIFile((FileInfo) obj, version));
            } else if (obj instanceof Folder) {
                result.setData(new XUIFile((Folder) obj, version));
            }

        } catch (JDSException e) {
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());
        }
        return result;
    }


    @MethodChinaName(cname = "打开文件夹")
    @RequestMapping(value = {"openFolder"}, method = {RequestMethod.POST})
    public @ResponseBody
    ListResultModel<List<XUIFile>> openFolder(String path, String projectName, Boolean hasFile) {
        ListResultModel<List<XUIFile>> result = new ListResultModel<List<XUIFile>>();
        String[] systemFiles = new String[]{"ProjectConfig.cfg", "xuiconf.js"};
        List<XUIFile> modules = new ArrayList<XUIFile>();
        Folder folder = null;
        ProjectVersion version = null;
        try {
            if (projectName != null) {
                if (path == null || projectName.equals(path)) {
                    path = "";
                }
                if (path.startsWith(projectName)) {
                    path = path.substring(projectName.length() + 1);
                }
                folder = getClient().getFolderByPath(path, projectName);
                version = getClient().getProjectVersionByName(projectName);
            } else {
                folder = this.getVfsClient().getFolderByPath(path);
            }

            if (folder != null) {
                List<Folder> folders = folder.getChildrenList();
                PackageType[] packageTypes = version.getProject().getProjectType().getPackageTypes();
                for (Folder cfolder : folders) {
                    String folderPath = StringUtility.replace(cfolder.getPath(), version.getPath(), "/");
                    PackagePathType packagePathType = PackagePathType.startPath(folderPath);
                    if (packagePathType == null || packagePathType.getApiType() == null || Arrays.asList(packageTypes).contains(packagePathType.getApiType())) {
                        boolean isSystem = false;
                        for (String name : systemFiles) {
                            if (cfolder.getName().equals(name)) {
                                isSystem = true;
                            }
                        }
                        if (!isSystem) {
                            modules.add(new XUIFile(cfolder, version));
                        }
                    }
                }
                List<FileInfo> infos = folder.getFileList();
                Set<String> classNameSet = new HashSet<>();
                for (FileInfo fileInfo : infos) {
                    boolean isSystem = false;
                    for (String name : systemFiles) {
                        if (fileInfo.getName().equals(name)) {
                            isSystem = true;
                        }
                    }
                    if (!isSystem) {
                        if (!fileInfo.getName().endsWith(".cls")) {
                            modules.add(new XUIFile(fileInfo, version));
                        } else {
                            classNameSet.add(fileInfo.getPath());
                        }
                    }
                }

                Set<EUModule> moduleSet = this.getClient().loadModules(classNameSet, version.getVersionName());
                for (EUModule module : moduleSet) {
                    if (module != null) {
                        modules.add(new XUIFile(module));
                    }
                }


            }
            result.setData(modules);
        } catch (JDSException e) {
            result = new ErrorListResultModel<>();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());

        }

        return result;
    }


    @MethodChinaName(cname = "系统方法")
    @RequestMapping(value = {"request"}, method = {RequestMethod.GET
            , RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIModule> request(String key, String paras, String projectName) {
        ResultModel<XUIModule> result = new ResultModel<XUIModule>();
        XUIParas param = JSONObject.parseObject(paras, XUIParas.class);
        String path = param.getPath();
        XUIModule xuiModule = new XUIModule();
        if (param.getAction().equals("open") || param.getAction().equals("refresh")) {
            List<XUIFile> modules = xuiModule.getFiles();
            try {
                ProjectVersion version = getClient().getProjectVersionByName(projectName);
                if (param.getAction().equals("refresh")) {
                    getVfsClient().clearCache(path);
                }
                Folder folder = getClient().getFolderByPath(path, projectName);

                if (folder != null) {
                    if (folder != null) {
                        List<Folder> folders = folder.getChildrenList();
                        for (Folder cfolder : folders) {
                            modules.add(new XUIFile(cfolder, version));
                        }
                        if ((param.getType() == null || param.getType() != 0) && (param.getDeep() == null || !param.getDeep().equals("0"))) {
                            List<FileInfo> infos = folder.getFileList();
                            Map<String, String> nameMap = new HashMap<String, String>();
                            for (FileInfo fileInfo : infos) {

                                if (param.getPattern() != null && !param.getPattern().equals("")) {
                                    Pattern p = Pattern.compile(param.getPattern());
                                    Matcher matcher = p.matcher(fileInfo.getName());
                                    modules.add(new XUIFile(fileInfo, version));
                                } else {
                                    modules.add(new XUIFile(fileInfo, version));
                                }
                            }
                        }

                    }
                }
                result.setData(xuiModule);
            } catch (JDSException e) {
                result = new ErrorResultModel();
                ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
                ((ErrorResultModel) result).setErrdes(e.getMessage());

            }
        }
        return result;
    }


    @MethodChinaName(cname = "保存文件内容")
    @RequestMapping(value = {"saveContent"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<XUIModule> saveContent(String projectName, String className, String content, String jscontent, String path, EUFileType fileType) {
        ResultModel<XUIModule> result = new ResultModel<XUIModule>();
        XUIModule xuiModule = new XUIModule();
        List<CustomModuleBean> moduleBeans = new ArrayList<>();
        try {
            ProjectVersion version = getClient().getProjectVersionByName(projectName);
            if (path != null && path.endsWith(".cls")) {
                fileType = EUFileType.EUClass;
            }
            switch (fileType) {
                case EUClass:
                    if (path.endsWith(".js") && jscontent != null) {
                        this.getClient().saveFile(new StringBuffer(jscontent), path, projectName);
                    }
                    if (className != null && !className.equals("")) {
                        EUModule euModule = version.getModule(className);
                        if (euModule == null) {
                            euModule = version.createModule(path);
                        }
                        ModuleComponent omoduleComponent = euModule.getComponent();
                        ModuleComponent moduleComponent = JSONObject.parseObject(content, ModuleComponent.class);
                        if (omoduleComponent != null && omoduleComponent.getFormulas() != null) {
                            moduleComponent.setFormulas(omoduleComponent.getFormulas());
                        }
                        euModule.setComponent(moduleComponent);
                        euModule.update(true);
                    }
                    break;
                case EUFile:
                    this.getClient().saveFile(new StringBuffer(jscontent), path, projectName);
                    break;
            }
            result.setData(xuiModule);
        } catch (Exception e) {
            e.printStackTrace();
            result = new ErrorResultModel();
            ((ErrorResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorResultModel) result).setErrdes(e.getMessage());

        }


        return result;
    }

    @MethodChinaName(cname = "删除文件版本")
    @RequestMapping(value = {"delFileVersion"}, method = {RequestMethod.POST})
    public @ResponseBody
    ResultModel<Boolean> delFileVersion(String paths, String projectName) {
        ResultModel<Boolean> result = new ResultModel<Boolean>();
        String[] versionIdArr = StringUtility.split(paths, ";");
        for (String versionId : versionIdArr) {
            try {
                getVfsClient().deleteFileVersion(versionId);
            } catch (JDSException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @MethodChinaName(cname = "获取所有版本")
    @RequestMapping(value = {"getAllFileVersion"}, method = {RequestMethod.POST})
    public @ResponseBody
    ListResultModel<List<XUIFileVersion>> getAllFileVersion(String path, String projectName) {
        ListResultModel<List<XUIFileVersion>> result = new ListResultModel<List<XUIFileVersion>>();
        List<XUIFileVersion> allversions = new ArrayList<XUIFileVersion>();
        try {

            FileInfo fileInfo = getClient().getFileByPath(path, projectName);
            List<FileVersion> versions = fileInfo.getVersionList();
            result = PageUtil.getDefaultPageList(versions, XUIFileVersion.class);
        } catch (JDSException e) {
            result = new ErrorListResultModel();
            ((ErrorListResultModel) result).setErrcode(JDSException.APPLICATIONNOTFOUNDERROR);
            ((ErrorListResultModel) result).setErrdes(e.getMessage());
        }

        return result;
    }


    ESDClient getClient() throws JDSException {

        ESDClient client = ESDFacrory.getAdminESDClient();

        return client;
    }

    public CtVfsService getVfsClient() {

        CtVfsService vfsClient = CtVfsFactory.getCtVfsService();
        return vfsClient;
    }
}
